﻿using System;
using System.Collections;

using BizElements.Core;

namespace BizElements.BusinessLayer
{
    /// <summary>
    /// Collection of <see cref="DisplayItem"/> objects.
    /// </summary>
    [Serializable]
    public sealed class DisplayItemCollection : IBindableFieldCollection
    {
        #region Fields.

        ArrayList list = new ArrayList();

        #endregion

        #region Add, Remove, Clear.

        /// <summary>
        /// Adds an item to the collection.
        /// </summary>
        /// <param name="item">Any select item.</param>
        /// <param name="caption">Item caption.</param>
        /// <returns>Item that was added to the collection.</returns>
        public DisplayItem Add(SelectItem item, string caption)
        {
            DisplayItem newItem = new DisplayItem(item, caption);
            this.list.Add(newItem);
            return newItem;
        }

        /// <summary>
        /// Adds an item to the collection.
        /// </summary>
        /// <param name="item">Display item.</param>
        /// <returns>Item that was added to the collection.</returns>
        public DisplayItem Add(DisplayItem item)
        {
            this.list.Add(item);
            return item;
        }

        /// <summary>
        /// Adds an item to the collection.
        /// </summary>
        /// <param name="column">Database column.</param>
        /// <param name="caption">Item caption.</param>
        /// <returns>Item that was added to the collection.</returns>
        public DisplayItem Add(IDbColumn column, string caption)
        {
            return Add(new SelectItem(column), caption);
        }

        /// <summary>
        /// Adds an item to the collection.
        /// </summary>
        /// <param name="column">Database column.</param>
        /// <param name="caption">Item caption.</param>
        /// <param name="isHidden">Whether the field should bi hidden from view in the user interface.</param>
        /// <returns>Item that was added to the collection.</returns>
        public DisplayItem Add(IDbColumn column, string caption, bool isHidden)
        {
            DisplayItem field = Add(new SelectItem(column), caption);
            field.IsHidden = isHidden;
            return field;
        }

        /// <summary>Removes the field with the specified name.</summary>
        /// <param name="bindingName">Alias/name of the item.</param>
        public void Remove(string bindingName)
        {
            int idxOfItemToRemove = ArrayUtil.IndexOf<IBindableField>(this.list, (field) => (field.BindingName == bindingName));
            if (idxOfItemToRemove >= 0)
                this.list.RemoveAt(idxOfItemToRemove);
        }

        /// <summary>Remove all elements from the collection.</summary>
        public void Clear()
        {
            this.list.Clear();
        }

        #endregion

        #region Properties and indexers.

        /// <summary>
        /// Gets the element at the specified index.
        /// </summary>
        /// <param name="index">The zero-based index of the element to get or set. </param>
        /// <returns>The element at the specified index.</returns>
        public DisplayItem this[int index]
        {
            get { return (DisplayItem)this.list[index]; }
        }

        IBindableField IBindableFieldCollection.this[int index]
        {
            get { return this[index]; }
        }

        /// <summary>
        /// Searches the collection for the item with the specified <see cref="DisplayItem.BindingName"/>.
        /// </summary>
        /// <param name="bindingName">Alias/name of the item.</param>
        /// <returns>Specified field or <b>null</b> if a item with the given name is not found in the collection.</returns>
        public DisplayItem this[string bindingName]
        {
            get
            {
                for (int i = 0; i < this.Count; i++)
                    if (this[i].BindingName == bindingName)
                        return this[i];

                return null;
            }
        }

        IBindableField IBindableFieldCollection.this[string bindingName]
        {
            get { return this[bindingName]; }
        }

        /// <summary>
        /// Gets the number of elements actually contained in the collection.
        /// </summary>
        public int Count
        {
            get { return this.list.Count; }
        }

        #endregion

        #region IEnumerable.

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.list.GetEnumerator();
        }

        #endregion
    }
}
